// index.js

import Util from "../../utils/util";
const BLEUtil = require("../../utils/ble/util.js");

// 获取应用实例
const app = getApp();

// 字符串转byte
function stringToBytes(str) {
  var array = new Uint8Array(str.length);
  for (var i = 0, l = str.length; i < l; i++) {
    array[i] = str.charCodeAt(i);
  }
  console.log(array);
  return array.buffer;
}

// ArrayBuffer转16进度字符串示例
function ab2hex(buffer) {
  var hexArr = Array.prototype.map.call(new Uint8Array(buffer), function (bit) {
    return ("00" + bit.toString(16)).slice(-2);
  });
  return hexArr.join("");
}

//字符串转2进制
function strToBinary(str) {
  if (str === "") return "";
  var hexCharCode = [];
  // 　　hexCharCode.push("0x");
  for (var i = 0; i < str.length; i++) {
    hexCharCode.push(str.charCodeAt(i).toString(2));
  }
  console.log("return hexCharCode:", hexCharCode.join(""));
  return hexCharCode.join("");
}

//字符串转16进制
function strToHexCharCode(str) {
  if (str === "") return "";
  var hexCharCode = [];
  // 　　hexCharCode.push("0x");
  for (var i = 0; i < str.length; i++) {
    hexCharCode.push(str.charCodeAt(i).toString(16));
  }
  console.log("return hexCharCode:", hexCharCode.join(""));
  return hexCharCode.join("");
}

Page({
  data: {
    motto: "Hello World",
    userInfo: {},
    hasUserInfo: false,
    canIUse: wx.canIUse("button.open-type.getUserInfo"),
    canIUseGetUserProfile: false,
    canIUseOpenData:
      wx.canIUse("open-data.type.userAvatarUrl") &&
      wx.canIUse("open-data.type.userNickName"), // 如需尝试获取用户信息可改为false

    devices: [],
    deviceName: "",
    deviceId: "",
    services: [],
    serviceId: "",
    chs: [],
    isOpenBLE: true,
    _discoveryStarted: false,
  },

  // 事件处理函数
  bindViewTap() {
    wx.navigateTo({
      url: "../logs/logs",
    });
  },

  async onLoad() {
    if (wx.getUserProfile) {
      this.setData({
        canIUseGetUserProfile: true,
      });
    }

    wx.setNavigationBarTitle({
      title: "测试BLE",
    });
  },
  async onShow() {
    // 扫描周围的蓝牙设备
    this.OpenBluetoothAdapter();
  },

  // 初始化蓝牙模块，并持续扫描周围的蓝牙设备
  OpenBluetoothAdapter() {
    var this_page = this;
    wx.openBluetoothAdapter({
      success: (res) => {
        console.log("openBluetoothAdapter success", res);
        this.StartBluetoothDevicesDiscovery();
      },
      fail: (res) => {
        if (res.errCode === 10001) {
          // 手机没有开启蓝牙权限，提示用户去开启
          console.log("onBluetoothAdapterStateChange", res);
          this_page.setData({
            isOpenBLE: false,
          });
          wx.onBluetoothAdapterStateChange(function (res) {
            if (res.available) {
              this_page.setData({
                isOpenBLE: true,
              });
              this_page.StartBluetoothDevicesDiscovery();
            }
          });
        }
      },
    });
  },

  // 开启搜索蓝牙
  StartBluetoothDevicesDiscovery() {
    if (this._discoveryStarted) {
      return;
    }
    this._discoveryStarted = true;
    wx.startBluetoothDevicesDiscovery({
      allowDuplicatesKey: true,
      success: (res) => {
        console.log("startBluetoothDevicesDiscovery success", res);
        // 开启搜索功能成功后监听发现新设备事件
        this.OnBluetoothDeviceFound();
      },
    });
  },

  // 搜索到蓝牙设备的回调函数
  OnBluetoothDeviceFound() {
    wx.onBluetoothDeviceFound((res) => {
      // 找到了蓝牙设备
      // 只显示BOD蓝牙
      const bodDevices = res.devices.filter((i) => i.name.startsWith("BOD"));
      console.log("bodDevices:", bodDevices);
      // 看是否已经存在
      const ids = this.data.devices.map((i) => i.deviceId);
      if (ids.includes(res.devices[0].deviceId)) return;

      const arr = [...this.data.devices, ...bodDevices];
      // console.log(res.devices);
      this.setData({
        devices: arr,
      });
    });
  },

  // 获取本机蓝牙适配器状态
  GetBluetoothAdapterState() {
    wx.getBluetoothAdapterState({
      success: (res) => {
        console.log("getBluetoothAdapterState", res);
        if (res.discovering) {
          this.OnBluetoothDeviceFound();
        } else if (res.available) {
          this.StartBluetoothDevicesDiscovery();
        }
      },
      fail: (res) => {},
    });
  },
  // 获取蓝牙服务
  GetBLEDeviceServices(deviceId) {
    wx.showLoading({
      title: "获取服务中...",
    });
    const that = this;
    wx.getBLEDeviceServices({
      deviceId,
      fail: (err) => {
        wx.showToast({
          title: "获取服务失败",
        });
        wx.hideLoading();
      },
      complete: () => {
        wx.hideLoading();
      },
      success: (res) => {
        wx.hideLoading();
        this.setData({
          deviceId,
        });
        console.log("获取到的服务：", res.services);
        // 获取蓝牙服务成功
        that.setData({
          services: res.services.filter((i) => i.isPrimary),
        });
        if (res.services.length === 0) {
          wx.showToast({
            title: "未获取到服务",
          });
        } else {
          wx.showToast({
            title: "获取服务成功",
          });
        }
      },
    });
  },

  // 获取蓝牙特征值
  GetBLEDeviceCharacteristics(e) {
    wx.showLoading({
      title: "获取特征值中...",
    });
    const deviceId = this.data.deviceId;
    const serviceId = e.mark.serviceId;
    this.setData({
      serviceId,
    });
    var that = this;

    wx.getBLEDeviceCharacteristics({
      deviceId,
      serviceId,
      success: (res) => {
        wx.hideLoading();
        console.log("getBLEDeviceCharacteristics success", res.characteristics);
        // 获取特征值成功
        this.setData({
          chs: res.characteristics,
        });
        if (res.characteristics.length === 0) {
          wx.showToast({
            title: "未获取到特征值",
          });
        } else {
          wx.showToast({
            title: "获取特征值成功",
          });
        }
        for (let i = 0; i < res.characteristics.length; i++) {
          let item = res.characteristics[i];
          if (item.properties.notify || item.properties.indicate) {
            console.log("支持接收蓝牙通知");
            wx.notifyBLECharacteristicValueChange({
              deviceId,
              serviceId,
              characteristicId: item.uuid,
              state: true,
              success(res) {
                // 读取低功耗蓝牙设备的特征值的二进制数据值。注意：必须设备的特征值支持 read 才可以成功调用。
                console.log("readBLECharacteristicValue:", res);
                wx.readBLECharacteristicValue({
                  deviceId,
                  serviceId,
                  characteristicId: item.uuid,
                  success(res) {
                    console.log("readBLECharacteristicValue:", res.errCode);
                  },
                });
              },
            });
          }
        }
      },
      fail(res) {
        wx.hideLoading();
        wx.showToast({
          title: "获取特征值失败",
        });
        console.error("getBLEDeviceCharacteristics", res);
      },
    });
    // 操作之前先监听，保证第一时间获取数据
    wx.onBLECharacteristicValueChange((characteristic) => {
      console.log(
        `characteristic ${
          characteristic.characteristicId
        } has changed, now is ${ab2hex(characteristic.value)}`
      );

      wx.showToast({
        title:
          characteristic.characteristicId +
          "写入成功，现值为" +
          ab2hex(characteristic.value),
        duration: 2000,
      });
    });
  },
  // 连接低功耗蓝牙设备
  async CreateBLEConnection(e) {
    wx.showLoading({
      title: "连接中...",
    });
    const name = e.mark.name;
    const deviceId = e.mark.deviceId;
    this.setData({
      deviceName: name || "未命名",
    });
    console.log("连接的蓝牙信息：", deviceId);
    // 连接蓝牙前先停止搜索
    await this.StopBluetoothDevicesDiscovery();
    wx.createBLEConnection({
      deviceId,
      success: (res) => {
        wx.hideLoading();
        wx.showToast({
          title: "蓝牙已连接",
        });
        this.GetBLEDeviceServices(deviceId);
      },
      fail: (res) => {
        wx.hideLoading();
        wx.showToast({
          title: "连接失败",
          icon: "none",
          duration: 2000,
        });
      },
    });
  },

  // 写数据
  WriteBLECharacteristicValue(e) {
    wx.showLoading({
      title: "写入数据中...",
    });
    const characteristicId = e.mark.characteristicId;
    const testStr = "SysTime:190727123000";

    const that = this;
    console.log("e.mark.characteristicId: ", e.mark.characteristicId);
    console.log("参数：", {
      deviceId: that.data.deviceId,
      serviceId: that.data.serviceId,
      characteristicId,
    });
    wx.writeBLECharacteristicValue({
      deviceId: that.data.deviceId,
      serviceId: that.data.serviceId,
      characteristicId,
      value: stringToBytes(testStr),
      success(res) {
        wx.hideLoading();
        wx.showToast({
          title: "写入特征值成功",
        });
        console.log("写入特征值 success", res.errMsg);
      },
      fail(res) {
        wx.hideLoading();
        wx.showToast({
          title: "写入特征值失败",
        });
        console.error("写入特征值失败", res);
      },
    });
  },

  // 停止搜索蓝牙
  StopBluetoothDevicesDiscovery() {
    wx.stopBluetoothDevicesDiscovery({
      success: (res) => {
        console.log("stopBluetoothDevicesDiscovery success", res);
      },
    });
  },

  //断开蓝牙连接
  CloseBLEConnection() {
    var this_page = this;
    wx.closeBLEConnection({
      deviceId: this.data.deviceId,
      success: (res) => {},
    });
    this.setData({
      connected: false,
      chs: [],
      canWrite: false,
    });
  },

  // 关闭蓝牙模块
  CloseBluetoothAdapter() {
    wx.closeBluetoothAdapter();
    this._discoveryStarted = false;
  },

  getUserProfile(e) {
    // 推荐使用wx.getUserProfile获取用户信息，开发者每次通过该接口获取用户个人信息均需用户确认，开发者妥善保管用户快速填写的头像昵称，避免重复弹窗
    wx.getUserProfile({
      desc: "展示用户信息", // 声明获取用户个人信息后的用途，后续会展示在弹窗中，请谨慎填写
      success: (res) => {
        console.log(res);
        this.setData({
          userInfo: res.userInfo,
          hasUserInfo: true,
        });
      },
    });
  },
  getUserInfo(e) {
    // 不推荐使用getUserInfo获取用户信息，预计自2021年4月13日起，getUserInfo将不再弹出弹窗，并直接返回匿名的用户个人信息
    console.log(e);
    this.setData({
      userInfo: e.detail.userInfo,
      hasUserInfo: true,
    });
  },
});
